#coding=utf8
__author__ = 'alex'
import datetime
import uuid
from sqlalchemy import Column,Integer,String,DateTime,Boolean,Text,UniqueConstraint,Table, MetaData,ForeignKey, Numeric
from sqlalchemy.ext.declarative import declarative_base, declared_attr
from sqlalchemy.orm import relationship,backref
from decimal import Decimal
from utils import hash_passwd,read_random, check_passwd
from flask import g


TABLEARGS = {
    'mysql_engine': 'InnoDB',
    'mysql_charset':'utf8'
}

class DeclaredBase(object):
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()
    id =  Column(Integer, primary_key=True, autoincrement=True)
    create_time = Column(DateTime, default=datetime.datetime.now, index=True)
    last_modify = Column(DateTime, default=datetime.datetime.now, index=True)

Base = declarative_base(cls=DeclaredBase)


class Admin(Base):
    name = Column(String(40))
    password = Column(String(40))
    nick = Column(String(40))
    status = Column(Integer)
    __table_args__ = (
        UniqueConstraint(name,),
        TABLEARGS
    )
    def __init__(self,name, password, nick):
        self.name = name
        self.password = hash_passwd(password)
        self.nick = nick
        self.status = 0

    def verify(self, password):
        return check_passwd(password,self.password)

class Catalogs(Base):
    name = Column(String(20))
    forward_id = Column(Integer)
    level = Column(Integer)
    idx = Column(Integer)
    __table_args__ = (
        UniqueConstraint(name,),
        TABLEARGS
    )
    def __init__(self,name, forward_id, level, idx):
        self.name = name
        self.forward_id = forward_id
        self.level = level
        self.idx = idx

    def make_child(self, name):
        return g.db.add(Catalogs(name, self.id, self.level+1))

    @property
    def has_document(self):
        return g.db.query(Document).filter(Document.catalog_id==self.id).count()

    @property
    def nexts(self):
        data = list(g.db.query(Catalogs).filter(Catalogs.forward_id==self.id).order_by(Catalogs.idx.asc()))
        if not data:
            data = list(g.db.query(Document).filter(Document.catalog_id==self.id).order_by(Document.id.desc()))
        return data

    def indexed_next(self):
        data = self.nexts
        idx = 0
        for d in data:
            yield idx,d
            idx+=1

    @property
    def all_childs(self):
        data = []
        for child in self.nexts:
            data.append(child)
            if not child.doc_type:
                for child_0 in child.nexts:
                    if not child_0.doc_type:
                        data.append(child_0)
                        for child_1 in child_0.nexts:
                            if not child_1.doc_type:
                                data.append(child_1)
        #data.reverse()
        return data

    @property
    def text(self):
        lines = []
        for child in self.all_childs:
            if not child.doc_type:
                lines.append(u"".join(["-"*(child.level),child.name]))
        return u"\n".join(lines)

    @property
    def doc_type(self):
        return False

class Document(Base):
    title = Column(String(200))
    content = Column(Text)
    catalog_id = Column(Integer)
    poster = Column(String(40))
    __table_args__ = (
        UniqueConstraint(title,),
        TABLEARGS
    )
    def __init__(self, title, content, catalog_id, poster):
        self.title = title
        self.content = content
        self.catalog_id = catalog_id
        self.poster = poster

    def append_attachment(self, name, attach_type, content):
        return g.db.add(Attachment(self.id, name, attach_type, content))

    @property
    def attachments(self):
        return g.db.query(Attachment).filter(Attachment.document_id==self.id).order_by(Attachment.id.asc())

    @property
    def path_catalogs(self):
        catalog = g.db.query(Catalogs).get(self.catalog_id)
        datas = [catalog,]
        while True:
            try:
                catalog = g.db.query(Catalogs).get(catalog.forward_id)
                if not catalog:
                    break
                datas.append(catalog)
            except:
                break
        datas.reverse()
        return datas

    @property
    def doc_type(self):
        return True

    @property
    def nexts(self):
        return []

class Attachment(Base):
    document_id = Column(Integer)
    name = Column(String(40))
    attachment_type =Column(Integer) #TODO: 0=文本，1=url
    text_content = Column(Text)
    url_content = Column(String(100))
    __table_args__ =  TABLEARGS

    def __init__(self, document_id, name, attachment_type, content):
        self.document_id = document_id
        self.name = name
        self.attachment_type = attachment_type
        if attachment_type:
            self.url_content = content
        else:
            self.text_content = content

    def __repr__(self):
        return self.url_content if self.attachment_type else self.text_content

    @property
    def content(self):
        return str(self)

